//
//  meefftest8.mm
//  meefftest8
//
//  Created by global on 2023/12/6.
//  Copyright (c) 2023 ___ORGANIZATIONNAME___. All rights reserved.
//

// CaptainHook by Ryan Petrich
// see https://github.com/rpetrich/CaptainHook/

#if TARGET_OS_SIMULATOR
#error Do not support the simulator, please use the real iPhone Device.
#endif
#include "fishhook.h"
#include <sys/sysctl.h>
#import <CoreLocation/CoreLocation.h>

#include <substrate.h>
#import <Foundation/Foundation.h>
#import "CaptainHook/CaptainHook.h"
#include <notify.h> // not required; for examples only
#import <UIKit/UIKit.h>
#import <Cycript/Cycript.h>
#import <CoreLocation/CoreLocation.h>
#import "MyDelegate.h"
#include <substrate.h>
#include <sys/utsname.h>
// Objective-C runtime hooking using CaptainHook:
//   1. declare class using CHDeclareClass()
//   2. load class using CHLoadClass() or CHLoadLateClass() in CHConstructor
//   3. hook method using CHOptimizedMethod()
//   4. register hook using CHHook() in CHConstructor
//   5. (optionally) call old method using CHSuper()


typedef void (^DataTaskCompletionHandler)(NSData *data, NSURLResponse *response, NSError *error);

static  NSUUID *uuidString;
static  NSUUID *uuidString2;

@interface meefftest8 : NSObject

@end

@implementation meefftest8

-(id)init
{
	if ((self = [super init]))
	{
	}

    return self;
}

@end


@class ClassToHook;

CHDeclareClass(ClassToHook); // declare class
CHDeclareClass(NSURLSession)
CHDeclareClass(ASIdentifierManager)
CHDeclareClass(UIDevice)
CHDeclareClass(CLLocationManager)
CHDeclareClass(NSLocale)
CHDeclareClass(NSFileManager)
CHDeclareClass(NSProcessInfo)



CHOptimizedMethod(0, self, void, ClassToHook, messageName) // hook method (with no arguments and no return value)
{
	// write code here ...
	
	CHSuper(0, ClassToHook, messageName); // call old (original) method
}

CHOptimizedMethod(2, self, BOOL, ClassToHook, arg1, NSString*, value1, arg2, BOOL, value2) // hook method (with 2 arguments and a return value)
{
	// write code here ...

	return CHSuper(2, ClassToHook, arg1, value1, arg2, value2); // call old (original) method and return its return value
}

static void WillEnterForeground(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
	// not required; for example only
}

static void ExternallyPostedNotification(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
	// not required; for example only
}




CHOptimizedMethod(0, self, NSString    *, UIDevice, systemVersion) // hook method (with no arguments and no return value)
{
//   NSString* res = CHSuper(0, UIDevice, systemVersion); // call old (original) method
    NSString* re =[MyDelegate randomSystemVersion];
    NSLog(@"系统版本%@",re);

    return re;
}

CHOptimizedMethod(0, self, float, UIDevice, batteryLevel) // hook method (with no arguments and no return value)
{
//    float res = CHSuper(0, UIDevice, batteryLevel); // call old (original) method
    float re =[MyDelegate randomBatteryLevel];
    NSLog(@"电量%f", re);
    return re;
}

CHOptimizedMethod(0, self, int, UIDevice, batteryState) // hook method (with no arguments and no return value)
{
//    int res = CHSuper(0, UIDevice, batteryLevel); // call old (original) method
    NSLog(@"充电中");
    return 2;
}

CHOptimizedClassMethod(0, self, NSArray<NSString *>*, NSLocale, preferredLanguages) // hook method (with no arguments and no return value)
{
    NSArray<NSString *>* res = CHSuper(0, NSLocale, preferredLanguages); // call old (original) method
    NSLog(@"本地语言");
    return @[@"en-US",@"ko-KR"];
   // return @[@"zh-Hans",@"en"];
}

CHOptimizedClassMethod(0, self,NSString *, NSLocale, localeIdentifier) // hook method (with no arguments and no return value)
{
    NSString * res = CHSuper(0, NSLocale, localeIdentifier); // call old (original) method
    NSLog(@"地区设置的代码");
    return @"ko_KR";
}

CHOptimizedMethod(1, self,id, NSLocale, objectForKey,NSLocaleKey,key) // hook method (with no arguments and no return value)
{
    NSString * res = CHSuper(1, NSLocale, objectForKey,key); // call old (original) method
    NSLog(@"本地时区");
    //2 插件不执行
    if([key isEqualToString:NSLocaleCountryCode]){
          return @"KR";
     }
    return res;
}

// 原始的 sysctlbyname 函数指针
static int (*original_sysctlbyname)(const char *, void *, size_t *, void *, size_t);

// 替换的 sysctlbyname 函数
static int replaced_sysctlbyname(const char *a, void *b, size_t *c, void *d, size_t e) {
    if (b != NULL && strcmp(a, "hw.machine") == 0) {
        NSString* re =[MyDelegate randomDeviceModel];
        const char *cString = [re UTF8String];
        strcpy((char *)b, cString);
        NSLog(@"打印设备型号:%@",re);
        return 0;
    }
    return original_sysctlbyname(a, b, c, d, e);
}

static int (*original_uname)(struct utsname *);

int my_uname(struct utsname *buf) {
    int ret = original_uname(buf);
    if (ret == 0) {
        NSString* re =[MyDelegate randomDeviceModel];
        // 修改machine字段
        const char *cString = [re UTF8String];
        strcpy(buf->machine, cString);
        NSLog(@"打印设备型号2:%@",re);

    }
    return ret;
}


//float randomFloatBetween(float smallNumber, float bigNumber) {
//    float diff = bigNumber - smallNumber;
//    return (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * diff) + smallNumber;
//}

CHOptimizedMethod(2, self,NSDictionary *, NSFileManager, attributesOfFileSystemForPath,NSString *,path,error,NSError **,error) // hook method (with no arguments and no return value)
{
    NSDictionary  * res = CHSuper(2, NSFileManager, attributesOfFileSystemForPath,path,error,error); // call old (original) method
    float re =[MyDelegate randomFloatBetween:1.1 bigNumber:6.1];
    
    NSDictionary* dic =  @{
         @"NSFileSystemFreeNodes" : [NSNumber numberWithLong:175008520* re],
         @"NSFileSystemFreeSize" : [NSNumber numberWithLong:17920872448*re],
         @"NSFileSystemNodes" : [NSNumber numberWithLong:175160778*re],
         @"NSFileSystemNumber" : [NSNumber numberWithLong:16777224*re],
         @"NSFileSystemSize" : [NSNumber numberWithLong:31968497664*re]
     };
    NSLog(@"存储空间 %@",dic);
    return dic;

}



CHDeclareMethod0(NSUUID*, ASIdentifierManager, advertisingIdentifier){
    NSURL* ss = [NSURL new];
//    + (instancetype)requestWithURL:(NSURL *)URL;
    NSLog(@"广告标识符 特么method  :");
//    NSUUID* res = CHSuper0(ASIdentifierManager, advertisingIdentifier);
//    [WX20Singleton shareSingleton].uuid = res.UUIDString;
//NSStringFromSelector(SEL  _Nonnull aSelector)
    if(!uuidString2){
        uuidString2 = [MyDelegate advertisingIdentifier];
    }
    NSUUID* res2 = uuidString2;
    // [[NSUUID alloc]initWithUUIDString:@"7A5E2145-4C0A-B0E8-90A8-A1AE4496645C"];
                                            //7A5E2045-90A8-4C0A-B0E8-A1AE4496645C

    NSLog(@"广告标识符 特么method  %@",res2.UUIDString);
    return  res2;

}


CHDeclareMethod0(NSUUID*, UIDevice, identifierForVendor){
//    + (instancetype)requestWithURL:(NSURL *)URL;
//    NSUUID* res = CHSuper0(UIDevice, identifierForVendor);
//    [WX20Singleton shareSingleton].uuid = res.UUIDString;
//NSStringFromSelector(SEL  _Nonnull aSelector)
   
    if(!uuidString){
        uuidString = [MyDelegate identifierForVendor];
    }
    
//    NSString *uuidString = [uuid UUIDString];
    NSUUID* res2   = uuidString;
    // [[NSUUID alloc]initWithUUIDString:@"7A5E2045-90A8-B0E8-4C0A-A1AE4496645C"];
                                            //7A5E2045-90A8-4C0A-B0E8-A1AE4496645C
//                            WeChat        //F7F71871-EC53-4F51-8721-D43BFF84878F observe change
    NSLog(@"IDFV 厂商标识符 特么method  %@",res2.UUIDString);

    return  res2;

}


//@property(weak, nonatomic, nullable) id<CLLocationManagerDelegate> delegate;
CHOptimizedMethod1(self,void, CLLocationManager, setDelegate,id<CLLocationManagerDelegate>,arg1){

    NSLog(@"定位 特么method  :");
    //实现自定义类
//    locationManagerDelegate = arg1;
     [MyDelegate sharedInstance].delegate = arg1;
     CHSuper1(CLLocationManager, setDelegate,  [MyDelegate sharedInstance]);
    //F7F71871-EC53-4F51-8721-D43BFF84878F observe change
    

}

CHOptimizedMethod0(self,NSString *, NSProcessInfo, operatingSystemVersionString){

    NSString* re =[MyDelegate randomSystemVersion];
    NSLog(@"系统版本NSProcessInfo%@",re);
    return re;

}

CHOptimizedMethod0(self,NSString *, NSProcessInfo, operatingSystemVersion){

    NSString* re =[MyDelegate randomSystemVersion];
    NSLog(@"系统版本NSProcessInfo%@",re);
    return re;

}

CHOptimizedMethod2(self, NSURLSessionDataTask*, NSURLSession, dataTaskWithRequest, NSURLRequest*, request, completionHandler, DataTaskCompletionHandler, completionHandler){
//    self.delegate = [MyDelegate sharedInstance];
//    NSLog(@"打印请求头地址 %@",  request );
    //本地放一个请求头
    NSDictionary*   allHTTPHeaderFields = [request allHTTPHeaderFields];
    void (^newCompletionHandler)(NSData *  , NSURLResponse *  , NSError *  ) = ^(NSData *  data, NSURLResponse *  response, NSError *  error) {
        NSString * str  =[[NSString alloc] initWithData:data   encoding:NSUTF8StringEncoding];
        NSLog(@"打印请求头地址 %@",  request );
        NSLog(@"请求头参数%@", [request allHTTPHeaderFields]);
        NSData *httpBody = [request HTTPBody];
        if(httpBody){
            NSError *error;
            NSDictionary *jsonParams = [NSJSONSerialization JSONObjectWithData:httpBody options:NSJSONReadingAllowFragments error:&error];
            if (!error) {
                NSLog(@"请求参数: %@", jsonParams);
            } else {
            }
        }
        
        if(data){
            NSError *error;
            NSDictionary *jsonParams = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
           
        }
        NSLog(@"响应数据%@", str);
        NSLog(@"相应头%@", [ (NSHTTPURLResponse *)response  allHeaderFields]);

        

        if (completionHandler) {
            completionHandler(data, response, error);
        }
    };
    id resss = CHSuper2(NSURLSession, dataTaskWithRequest, request, completionHandler, newCompletionHandler);
    return resss;
}



CHConstructor // code block that runs immediately upon load
{
	@autoreleasepool
	{
		// listen for local notification (not required; for example only)
		CFNotificationCenterRef center = CFNotificationCenterGetLocalCenter();
		CFNotificationCenterAddObserver(center, NULL, WillEnterForeground, CFSTR("UIApplicationWillEnterForegroundNotification"), NULL, CFNotificationSuspensionBehaviorCoalesce);
		
		// listen for system-side notification (not required; for example only)
		// this would be posted using: notify_post("com.noyesrun.meeff.kr.meefftest8.eventname");
		CFNotificationCenterRef darwin = CFNotificationCenterGetDarwinNotifyCenter();
		CFNotificationCenterAddObserver(darwin, NULL, ExternallyPostedNotification, CFSTR("com.noyesrun.meeff.kr.meefftest8.eventname"), NULL, CFNotificationSuspensionBehaviorCoalesce);
		
		// CHLoadClass(ClassToHook); // load class (that is "available now")
		// CHLoadLateClass(ClassToHook);  // load class (that will be "available later")
		
		CHHook(0, ClassToHook, messageName); // register hook
		CHHook(2, ClassToHook, arg1, arg2); // register hook
        CHLoadLateClass(ASIdentifierManager);
        CHLoadLateClass(UIDevice);
        CHLoadLateClass(NSURLSession);
        CHLoadLateClass(CLLocationManager);
        CHLoadLateClass(NSLocale);
        CHLoadLateClass(NSFileManager);
    //    CHClassHook0(ASIdentifierManager, advertisingIdentifier);
        CHClassHook0(UIDevice, identifierForVendor);
        CHClassHook0(UIDevice, systemVersion);
        CHClassHook0(UIDevice, batteryLevel);
        CHClassHook0(UIDevice, batteryState);
        CHClassHook0(NSLocale, preferredLanguages);
        CHClassHook0(NSLocale, localeIdentifier);
        CHClassHook1(NSLocale, objectForKey);
        CHClassHook2(NSFileManager, attributesOfFileSystemForPath,error);
        CHClassHook1(CLLocationManager, setDelegate);
        CHClassHook2(NSURLSession, dataTaskWithRequest,completionHandler);

        CHClassHook0(NSProcessInfo, operatingSystemVersionString);
        CHClassHook0(NSProcessInfo, operatingSystemVersion);


        
	}
}


__attribute__((constructor))
    static void initialize() {
        struct rebinding sysctlbyname_rebinding = { "sysctlbyname", (void *)replaced_sysctlbyname, (void **)&original_sysctlbyname };
//           rebind_symbols(&sysctlbyname_rebinding, 1);
        struct rebinding sysctlbyname_rebinding2 = { "uname", (void *)my_uname, (void **)&original_uname };
        
            rebind_symbols(&sysctlbyname_rebinding, 1);
            rebind_symbols(&sysctlbyname_rebinding2, 2);


        
}

